﻿#ifndef JFUTUREWATCHER_P_H
#define JFUTUREWATCHER_P_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include <QList>
#include "jfuturewatcher.h"
#include "jfutureinterface_p.h"
#include "tools/jobjectobserver_p.h"

// - class JFutureWatcherBasePrivate -

#define J_USE_SIGNAL 0

#if J_USE_SIGNAL

#define J_EMIT_SIGNAL(_signal_params_) \
    Q_EMIT _signal_params_

#else

#define J_EMIT_SIGNAL(_signal_params_) \
    _emit_ ## _signal_params_
#endif

class JFutureWatcherBase;

class JFutureWatcherBasePrivate : public QObject, public JFutureCallOutInterface
{
    Q_OBJECT
    J_DECLARE_PUBLIC(JFutureWatcherBase)
    J_DECLARE_OBSERVER_PRIVATE(JFutureWatcherBase)
public:
    JFutureWatcherBasePrivate(JFutureWatcherBase *parent);

    void postCallOutEvent(const JFutureCallOutEvent &callOutEvent);
    void callOutInterfaceDisconnected();

    void sendCallOutEvent(JFutureCallOutEvent *event);

    bool event(QEvent *event);
#if J_USE_SIGNAL
Q_SIGNALS:
    void started();
    void finished();
    void canceled();
    void paused();
    void resumed();
    void resultReadyAt(int resultIndex);
    void resultsReadyAt(int beginIndex, int endIndex);
    void progressRangeChanged(int minimum, int maximum);
    void progressValueChanged(int progressValue);
    void progressTextChanged(const QString &progressText);
#endif
public Q_SLOTS:
    void _emit_started()
    { J_EMIT_OBSERVER_PRIVATE(JFutureWatcherBase, started()); }

    void _emit_finished()
    { J_EMIT_OBSERVER_PRIVATE(JFutureWatcherBase, finished()); }

    void _emit_canceled()
    { J_EMIT_OBSERVER_PRIVATE(JFutureWatcherBase, canceled()); }

    void _emit_paused()
    { J_EMIT_OBSERVER_PRIVATE(JFutureWatcherBase, paused()); }

    void _emit_resumed()
    { J_EMIT_OBSERVER_PRIVATE(JFutureWatcherBase, resumed()); }

    void _emit_resultReadyAt(int resultIndex)
    { J_EMIT_OBSERVER_PRIVATE(JFutureWatcherBase, resultReadyAt(resultIndex)); }

    void _emit_resultsReadyAt(int beginIndex, int endIndex)
    { J_EMIT_OBSERVER_PRIVATE(JFutureWatcherBase, resultsReadyAt(beginIndex, endIndex)); }

    void _emit_progressRangeChanged(int minimum, int maximum)
    { J_EMIT_OBSERVER_PRIVATE(JFutureWatcherBase, progressRangeChanged(minimum, maximum)); }

    void _emit_progressValueChanged(int progressValue)
    { J_EMIT_OBSERVER_PRIVATE(JFutureWatcherBase, progressValueChanged(progressValue)); }

    void _emit_progressTextChanged(const QString &progressText)
    { J_EMIT_OBSERVER_PRIVATE(JFutureWatcherBase, progressTextChanged(progressText.toStdString())); }

protected:
#if J_USE_SIGNAL
    void connectNotify(const char *signal);
    void disconnectNotify(const char *signal);
#endif

private:
    void init();

private:
    QList<JFutureCallOutEvent *> pendingCallOutEvents;
    QAtomicInt pendingResultsReady;
    int maximumPendingResultsReady;
#if J_USE_SIGNAL
    QAtomicInt resultAtConnected;
#endif
    bool _finished;
};

#endif  // JFUTUREWATCHER_P_H
